iT邦幫忙

2021 iThome 鐵人賽

DAY 9
0
Mobile Development

IOS菜逼八連續30天挑戰系列 第 9

Day 9 Swift語法-進階篇(2/5)-Inheritance

  • 分享至 

  • xImage
  •  

今天講一下有關class(類別)的繼承:沒有使用繼承的class,我們一般稱為"base class",繼承通常是這樣使用:

首先我們先宣告一個base class:

class userInformation {
    var currentUser = String()
    var information: String {
        return "當前使用者為 \(currentUser)"
    }
    func showAllUsers() {
        print("none")
    }
}

然後我們宣告他的子類

class User1: userInformation {
    var isOnline = false
    
}

如此一來,User1就是userInformation的子類(SubClass),而userInformation就是User1的父類,他會繼承父類的一切東西,例如currentUser跟information,當然在子類別裡,你可以去定義一些東西,譬如我就定義了一個"使用者是否在線上"的布林值,然後我們用下列方法把值取出來並顯示在終端機上

let allen = User1()
allen.isOnline = true
allen.currentUser = "allen"
print("使用者狀態: \(allen.information)")

上面我就對我子類別定義的"使用者是否在線上"對他的值的進行修改,當然子類別可以再被其他類別繼承,譬如這樣:

class Allen: User1 {
    var currentNumberOfUser = 1
}

然後一樣,我們去設定他的值,並打印出來,記得前面的要註解掉或刪除掉,然後我們可以看到,我在新的類別同樣也宣告一個新的變數叫currentNumberOfUser,我們一樣可以對他進行值得修改

let allen = Allen()
allen.isOnline = true
allen.currentNumberOfUser = 1
allen.currentUser = "allen"
print("顯示當前使用者: \(allen.information)")

從上面程式碼,我們可以看到"isOnline"還是可以修改的,且多了一個"currentNumberOfUser",因為我們Allen這個類別繼承了User1類別~

重寫方法(Overriding),我們可以重寫的方式去重新定義子類的東西,例如這樣:

override func showAllUsers() {
        print("使用者數:\(currentNumberOfUser)")
    }
}

然後我們把他打印出來:

allen.showAllUsers()

把這段程式碼加在我們的子類裡面,代表我們對 function "showAllUsers", 進行了重寫,原本應該要顯示的是"none",重寫後變成"使用者數:1"結果如下:

重寫屬性,譬如我們有個父類跟一個子類:

//父類
class temperature {
    
    var Temperature = 0.0
    
    var description: String {
        return "當前溫度:"
    }
    
    
    func dosomethingFunction() {
        //do something
    }
}

//子類
class currentTemperature: temperature {
    override var Temperature: Double {
        get {
            return 36.5
        }
        set {
            print(newValue)
        }
    }
    
    // do something
}

接著我們把他打印出來:

let student1 = currentTemperature()
print(student1.description)
student1.Temperature = 37.0 

可以注意到,我們設定一個新的值給他,是37.0,這樣我們就對Temperature進行了屬性重寫。

補充:
當我們子類要繼承的時候,無論繼承來的屬性是存儲型(let)的還是計算型(var)的屬性,子類並不知道繼承來的屬性是存儲型的還是計算型的(譬如:Temperature)它只知道繼承來的屬性會有一個名字和類型。所以你在重寫一個屬性時,必需將它的名字和類型都寫出來。然後我們可以自訂一個getter跟一個setter,當你使用setter作為重寫屬性的一部分,那你也必須提供一個getter,可以注意到上面的getter我們設定的值是 36.5 ,這是一個默認的值,譬如我們把"student1.Temperature = 37.0"這行程式碼,換成:

print(student1.Temperature)

結果如下:

這時候如果你不想為getter去提供一個默認的值,我們可以透過

return super.someProperty

這樣的方式來傳遞繼承得值,而someProperty就是我們要重寫的屬性的名子,譬如我們最一開始的程式碼:

class userInformation {
    var currentUser = String()
    var information: String {
        return "當前使用者為 \(currentUser)"
    }
    func showAllUsers() {
        print("none")
    }
}

class User: userInformation {
var currentNumberOfUser = 1
    var isOnline = false
    
}

class Allen: User {
        override var information: String {
            return super.information + " 使用者數量為:\(currentNumberOfUser)位"
        }
}

我們就把information的屬性重寫了~

重寫屬性觀察器,首先我們先了解什麼是屬性觀察器,屬性觀察器(property observer)會監控和回應屬性值的變化,每次屬性被設置新的值都會呼叫屬性觀察器,譬如我們希望使用者輸入密碼不能有特定的字符,或是我們規定他要大寫,我們就可以透過屬性觀察器,去把多餘的字符刪除,或是幫忙轉化成大寫,我們先做一個簡單的轉換大小寫的屬性觀察器:

class upperCased {
    var name = String() {
        willSet(name) {
            print("要轉換成大寫的字串:\(name)")
        }
        didSet {
            if (name == name.lowercased())  {
                self.name = name.uppercased()
                print(name)
            }
        }
    }
}
let lowerCased = upperCased()
lowerCased.name = "allen"
//結果:
//要轉換成大寫的字串:allen
//ALLEN

willSet 會在該值被存儲之前被調用
didSet 會在一個新值被存儲後被調用

接下來我們試看看重寫屬性觀察器:

class Tom: User {
    override var currentUser: String {
        didSet{
            self.currentNumberOfUser = currentNumberOfUser + 1
        }
    }
    override var information: String {
        return super.information + " 使用者數量為:\(currentNumberOfUser)位"
    }
}

結果:

最後如果我們如果要防止重寫的話:
在方法、屬性或者下標腳本的關鍵字前寫 final (譬如 final var , final func , final class func , final subscript )。


上一篇
Day 8 Swift語法-進階篇(1/5)-Closures
下一篇
Day 10 Swift語法-進階篇(3/5)-Initialization
系列文
IOS菜逼八連續30天挑戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言